package ysq.xyg.wxapi.api;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.StringUtil;
import org.apache.commons.collections.map.HashedMap;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.util.EntityUtils;
import ysq.xyg.base.util.BaseUtil;
import ysq.xyg.base.util.DateUtil;
import ysq.xyg.base.util.ProProperties;
import ysq.xyg.base.util.httpClient.HttpUtil;
import ysq.xyg.web.model.po.WebAccount;
import ysq.xyg.wxapi.model.base.*;
import ysq.xyg.wxapi.url.WxUrlUtil;

import java.io.*;
import java.security.MessageDigest;
import java.util.Date;
import java.util.Formatter;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Logger;

/**
 * 微信公众号接口
 *
 * @author shengQiang yu
 * @date 2019-04-28 8:41
 */
public class WxApi {
    private static Logger log= Logger.getLogger(WxApi.class.getName());
    /**
     * 获取接口访问凭证
     *
     * @param appId 公众号AppId
     * @param appSecret 公众号AppSecret
     * @return
     * @author shengQiang yu
     * @date 2019-04-28 8:42
     */
    public static AccessToken getAccessToken(String appId, String appSecret) {
        AccessToken token = null;
        String tockenUrl = WxUrlUtil.getTokenUrl(appId, appSecret);
        JSONObject jsonObject = HttpUtil.httpRequestAndReturnResult(tockenUrl, HttpMethod.GET, null);
        if (null != jsonObject && !jsonObject.containsKey("errcode")) {
            try {
                token = new AccessToken();
                token.setExpiresIn(jsonObject.getInteger("expires_in"));
                //提前3分钟结束
                token.setEndTime(DateUtil.getSecondOneDate(new Date(),token.getExpiresIn()-180));
                token.setAccessToken(jsonObject.getString("access_token"));
            } catch (JSONException e) {
                //获取token失败
                token = null;
            }
        }else if(null != jsonObject){
            token = new AccessToken();
            token.setErrcode(jsonObject.getInteger("errcode"));
        }
        return token;
    }

    /**
     * 获取OAuth2.0 Token
     *
     * @param appId 公众号AppId
     * @param appSecret 公众号AppSecret
     * @param code oauth2.0 code值
     * @return
     * @author shengQiang yu
     * @date 2019-04-28 8:42
     */
    public static OAuthAccessToken getOAuthAccessToken(String appId, String appSecret, String code) {
        OAuthAccessToken token = null;
        String tockenUrl = WxUrlUtil.getOAuthTokenUrl(appId, appSecret, code);
        JSONObject jsonObject = HttpUtil.httpRequestAndReturnResult(tockenUrl, HttpMethod.GET, null);
        if (null != jsonObject && !jsonObject.containsKey("errcode")) {
            try {
                token = new OAuthAccessToken();
                token.setOauthAccessToken(jsonObject.getString("access_token"));
                token.setExpiresIn(jsonObject.getInteger("expires_in"));
                token.setOpenid(jsonObject.getString("openid"));
                token.setScope(jsonObject.getString("scope"));
            } catch (JSONException e) {
                //获取token失败
                token = null;
            }
        }else if(null != jsonObject){
            token = new OAuthAccessToken();
            token.setErrcode(jsonObject.getInteger("errcode"));
        }
        return token;
    }

    /**
     * 获取OAuth2.0 UserInfo
     *
     * @param oAuthAccessToken OAuth2.0的token
     * @return
     * @author shengQiang yu
     * @date 2019-04-28 8:42
     */
    public static User getOAuthUserInfo(OAuthAccessToken oAuthAccessToken) {
        User user = null;
        String oAuthUserinfoUrl = WxUrlUtil.getOAuthUserinfoUrl(oAuthAccessToken.getOauthAccessToken(),oAuthAccessToken.getOpenid());
        JSONObject jsonObject = HttpUtil.httpRequestAndReturnResult(oAuthUserinfoUrl, HttpMethod.GET, null);
        if (null != jsonObject && !jsonObject.containsKey("errcode")) {
            try {
                user = new User();
                user.setOpenid(jsonObject.getString("openid"));
                user.setNickname(jsonObject.getString("nickname"));
                user.setHeadimgurl(jsonObject.getString("headimgurl"));
                if (jsonObject.containsKey("unionid")) {
                    String unionid=jsonObject.getString("unionid");
                    if(unionid!=null&&unionid!="") {
                        user.setUnionid(jsonObject.getString("unionid"));
                    }
                }
            } catch (JSONException e) {
                user = null;//获取token失败
            }
        }
        return user;
    }

    /**
     * 获取js ticket
     *
     * @param token 公众号token
     * @return
     * @author shengQiang yu
     * @date 2019-04-28 8:42
     */
    public static JSTicket getJSTicket(String token){
        JSTicket jsTicket = null;
        String jsTicketUrl = WxUrlUtil.getJsApiTicketUrl(token);
        JSONObject jsonObject = HttpUtil.httpRequestAndReturnResult(jsTicketUrl, HttpMethod.GET, null);
        if (null != jsonObject && jsonObject.containsKey("errcode") && jsonObject.getInteger("errcode") == 0) {
            try {
                jsTicket = new JSTicket();
                jsTicket.setTicket(jsonObject.getString("ticket"));
                jsTicket.setExpiresIn(jsonObject.getInteger("expires_in"));
            } catch (JSONException e) {
                //获取token失败
                jsTicket = null;
            }
        }else if(null != jsonObject){
            jsTicket = new JSTicket();
            jsTicket.setErrcode(jsonObject.getInteger("errcode"));
        }
        return jsTicket;
    }

     /**
     * 小程序获取用户信息
     * */
    protected static Map<String,Object> xcxAcceptUserInfo(String appId, String appSecret, String code){
        Map<String,Object> map=new HashedMap();
        String xcxUserInfoUrl = WxUrlUtil.getXcxUserInfoUrl(appId,appSecret,code);
        JSONObject jsonObject = HttpUtil.httpRequestAndReturnResult(xcxUserInfoUrl, HttpMethod.GET, null);
        if (null != jsonObject && !(jsonObject.containsKey("errcode"))) {
            map.put("errcode",0);
            map.put("openid",jsonObject.getString("openid"));
            map.put("sessionKey",jsonObject.getString("session_key"));
            if( jsonObject.containsKey("unionid")){
                map.put("unionid",jsonObject.getString("unionid"));
            }else{
                map.put("unionid","");
            }
        }else if(null != jsonObject){
            map.put("errcode",jsonObject.getInteger("errcode"));
            map.put("errmsg",jsonObject.getString("errmsg"));
        }
        return map;
    }
    /**
     * 小程序二维码图片信息
     * */
    protected static  Map<String,Object> xcxAcceptEwm(String access_token, String directory, String fileName, EwmMessage ewmMessage, boolean isCover){
        Map<String,Object> map=new HashedMap();
        File dirFile = new File(directory);
        File file = new File(directory,fileName);
        map.put("errcode",0);
        map.put("path",file.getAbsolutePath());
        if (!dirFile.isDirectory()) {
            // 如果目录不存在，则创建目录
            dirFile.mkdirs();
        }
        if (file.exists()&&(!isCover)){
            //当图片存在直接返回
        }else{
            String e= JSON.toJSONString(ewmMessage);
            String xcxUserInfoUrl = WxUrlUtil.getXcxEwmUrl(access_token);
            byte[] result = HttpUtil.httpsRequestByte(xcxUserInfoUrl, HttpMethod.POST, e);
            InputStream inputStream = null;
            OutputStream outputStream = null;
            inputStream = new ByteArrayInputStream(result);
            long num=result.length;
            try {
                if(num<200){
                    byte[] bytes = new byte[0];
                    bytes = new byte[inputStream.available()];
                    inputStream.read(bytes);
                    String str = new String(bytes);
                    map.put("errcode",1);
                    map.put("errmsg",str);
                }else{
                    if (!file.exists()){
                        file.createNewFile();
                    }
                    outputStream = new FileOutputStream(file);
                    int len = 0;
                    byte[] buf = new byte[1024];
                    while ((len = inputStream.read(buf, 0, 1024)) != -1) {
                        outputStream.write(buf, 0, len);
                    }
                    outputStream.flush();
                    outputStream.close();
                    inputStream.close();
                }

            } catch (IOException e1) {
                map.put("errcode",1);
                map.put("errmsg",e1.toString());
            }
        }
        return map;
    }
    /**
     * 小程序二维码图片信息
     * */
    protected static  Map<String,Object> xcxAcceptEwmXz(String access_token, String directory, String fileName, EwmMessage ewmMessage, boolean isCover){
        Map<String,Object> map=new HashedMap();
        File dirFile = new File(directory);
        File file = new File(directory,fileName);
        map.put("errcode",0);
        map.put("path",file.getAbsolutePath());
        if (!dirFile.isDirectory()) {
            // 如果目录不存在，则创建目录
            dirFile.mkdirs();
        }
        if (file.exists()&&(!isCover)){
            //当图片存在直接返回
        }else{
            String e= JSON.toJSONString(ewmMessage);
            String xcxUserInfoUrl = WxUrlUtil.getXcxEwmXzUrl(access_token);
            byte[] result = HttpUtil.httpsRequestByte(xcxUserInfoUrl, HttpMethod.POST, e);
            InputStream inputStream = null;
            OutputStream outputStream = null;
            inputStream = new ByteArrayInputStream(result);
            long num=result.length;
            try {
                if(num<200){
                    byte[] bytes = new byte[0];
                    bytes = new byte[inputStream.available()];
                    inputStream.read(bytes);
                    String str = new String(bytes);
                    map.put("errcode",1);
                    map.put("errmsg",str);
                }else{
                    if (!file.exists()){
                        file.createNewFile();
                    }
                    outputStream = new FileOutputStream(file);
                    int len = 0;
                    byte[] buf = new byte[1024];
                    while ((len = inputStream.read(buf, 0, 1024)) != -1) {
                        outputStream.write(buf, 0, len);
                    }
                    outputStream.flush();
                    outputStream.close();
                    inputStream.close();
                }

            } catch (IOException e1) {
                map.put("errcode",1);
                map.put("errmsg",e1.toString());
            }
        }
        return map;
    }
    /**
     * 发送模板消息
     * @return
     */
    public static JSONObject sendTemplateMessage(TemplateMessage tplMsg, String accessToken){
        if(tplMsg != null){
            return HttpUtil.httpRequestAndReturnResult(WxUrlUtil.getSendTemplateMessageUrl(accessToken), HttpMethod.POST, tplMsg.toString());
        }
        return null;
    }

    /**
     * 发送模板消息
     * @return
     */
    public static JSONObject sendCoupon(String url,String acceptOpenid,String title,String type,String name,String remark){
        TemplateMessage templateMessage=new TemplateMessage();
        WebAccount webAccount = WxMemoryCacheClient.getSingleWxAccountInfo();//获取缓存中的唯一账号
        if(webAccount!=null&& StringUtil.isNotEmpty(webAccount.getTemplateId())){
            templateMessage.setUrl(webAccount.getBaseUrl()+url);
            templateMessage.setOpenid(acceptOpenid);
            templateMessage.setTemplateId(webAccount.getTemplateId());
            Map<String,String> data=new HashMap<String, String>();
            data.put("first",title);
            data.put("keyword1",type);
            data.put("keyword2",name);
            data.put("remark",remark);
            templateMessage.setDataMap(data);
            JSONObject jsonObject= sendTemplateMessage(templateMessage,WxApiClient.getAccessToken());
            return jsonObject;
        }
        return null;
    }

    /**
     * 获取用户信息
     */
    public static User selectUser(String accessToken,String openId){
        JSONObject object = HttpUtil.httpRequestAndReturnResult(WxUrlUtil.getUserInfoUrl(accessToken,openId), HttpMethod.GET, null);
        if (null != object && !(object.containsKey("errcode"))) {
            User userEntity=new User();
            userEntity.setSubscribe(object.getString("subscribe"));
            userEntity.setOpenid(object.getString("openid"));
            userEntity.setNickname(object.getString("nickname"));
            userEntity.setSex(object.getInteger("sex"));
            userEntity.setLanguage(object.getString("language"));
            userEntity.setCity(object.getString("city"));
            userEntity.setProvince(object.getString("province"));
            userEntity.setCountry(object.getString("country"));
            userEntity.setHeadimgurl(object.getString("headimgurl"));
            if(userEntity.getHeadimgurl() !=null && !"".equals(userEntity.getHeadimgurl())){
                String size=getHeadImg(userEntity.getHeadimgurl(), "/");
                if("0".equals(size)){
                    userEntity.setHeadimgSize(640);
                }else{
                    userEntity.setHeadimgSize(Integer.parseInt(size));
                }
            }
            userEntity.setSubscribe_time(object.getString("subscribe_time"));
            userEntity.setUnionid(object.getString("unionid"));
            return userEntity;
        }
        return null;
    }
    public static String getHeadImg(String url,String dot){
        String[] v=url.split(dot);
        int num=v.length;
        return v[num-1];
    }
    /**
     * JSTicket 加密
     * */
    public static JSTicketShareResponse sign(String ticket, String url){
        String nonce_str = BaseUtil.uId();
        String timestamp = DateUtil.create_timestamp();
        String string1;
        String signature = "";

        //注意这里参数名必须全部小写，且必须有序
        string1 = "jsapi_ticket=" + ticket +
                "&noncestr=" + nonce_str +
                "&timestamp=" + timestamp +
                "&url=" + url;
        try{
            MessageDigest crypt = MessageDigest.getInstance("SHA-1");
            crypt.reset();
            crypt.update(string1.getBytes("UTF-8"));
            signature = byteToHex(crypt.digest());
        }catch (Exception e){
            e.printStackTrace();
        };
        return new JSTicketShareResponse(url,nonce_str,timestamp,signature);
    }
    private static String byteToHex(final byte[] hash) {
        Formatter formatter = new Formatter();
        for (byte b : hash)
        {
            formatter.format("%02x", b);
        }
        String result = formatter.toString();
        formatter.close();
        return result;
    }

}
